package demo4

import (
	"context"
	"fmt"
	"local/service_manager"
	"sync"
	"time"
)

// Message 定义消息结构
type Message struct {
	ID        int64
	Content   string
	Timestamp time.Time
}

// MessageQueue 定义消息队列
type MessageQueue struct {
	// mu       sync.RWMutex
	messages chan Message
	capacity int
}

// MessageService 定义消息处理服务结构
type MessageService struct {
	name        string
	description string
	lastError   *service_manager.ServiceError
	queue       *MessageQueue
	workers     int
	nextID      int64
}

// NewMessageQueue 创建新的消息队列
func NewMessageQueue(capacity int) *MessageQueue {
	return &MessageQueue{
		messages: make(chan Message, capacity),
		capacity: capacity,
	}
}

// NewMessageService 创建新的消息处理服务实例
func NewMessageService() *MessageService {
	return &MessageService{
		name:        "demo4_service",
		description: "示例服务 - 消息处理系统",
		queue:       NewMessageQueue(100),
		workers:     3, // 默认启动3个消费者
	}
}

// GetName 获取服务名称
func (s *MessageService) GetName() string {
	return s.name
}

// GetDescription 获取服务描述
func (s *MessageService) GetDescription() string {
	return s.description
}

// GetDependencies 获取服务依赖
func (s *MessageService) GetDependencies() []string {
	return nil
}

// GetLastError 获取最后一次错误
func (s *MessageService) GetLastError() *service_manager.ServiceError {
	return s.lastError
}

// OnStart 服务启动前的初始化
func (s *MessageService) OnStart(ctx context.Context) error {
	// 重新初始化消息队列
	s.queue = NewMessageQueue(100)
	s.nextID = 0 // 重置消息ID计数器

	fmt.Printf("[%s] 消息处理服务启动，队列容量: %d, 消费者数量: %d\n",
		time.Now().Format("15:04:05"),
		s.queue.capacity,
		s.workers)
	return nil
}

// producer 消息生产者
func (s *MessageService) producer(ctx context.Context) {
	ticker := time.NewTicker(2 * time.Second)
	defer ticker.Stop()

	for {
		select {
		case <-ctx.Done():
			return
		case <-ticker.C:
			msg := Message{
				ID:        s.nextID,
				Content:   fmt.Sprintf("消息-%d", s.nextID),
				Timestamp: time.Now(),
			}
			s.nextID++

			// 尝试发送消息到队列
			select {
			case s.queue.messages <- msg:
				fmt.Printf("[%s] 生产消息: %s\n",
					time.Now().Format("15:04:05"),
					msg.Content)
			default:
				// 队列已满，记录错误
				s.lastError = &service_manager.ServiceError{
					Time:    time.Now(),
					Message: "消息队列已满",
					Details: fmt.Sprintf("无法发送消息: %s", msg.Content),
				}
				fmt.Printf("[%s] 队列已满，消息丢弃: %s\n",
					time.Now().Format("15:04:05"),
					msg.Content)
			}
		}
	}
}

// consumer 消息消费者
func (s *MessageService) consumer(ctx context.Context, id int) {
	for {
		select {
		case <-ctx.Done():
			return
		case msg := <-s.queue.messages:
			// 模拟消息处理
			processTime := time.Duration(500+id*100) * time.Millisecond
			time.Sleep(processTime)
			fmt.Printf("[%s] 消费者-%d 处理消息: %s (处理时间: %v)\n",
				time.Now().Format("15:04:05"),
				id,
				msg.Content,
				processTime)
		}
	}
}

// Entry 服务入口函数
func (s *MessageService) Entry(ctx context.Context) error {
	// 启动生产者
	go s.producer(ctx)

	// 启动多个消费者
	var wg sync.WaitGroup
	for i := 0; i < s.workers; i++ {
		wg.Add(1)
		go func(id int) {
			defer wg.Done()
			s.consumer(ctx, id)
		}(i)
	}

	// 等待上下文取消
	<-ctx.Done()

	// 等待所有消费者退出
	wg.Wait()
	return nil
}

// OnStop 服务停止前的清理
func (s *MessageService) OnStop(ctx context.Context) error {
	fmt.Printf("[%s] 消息处理服务正在停止...\n",
		time.Now().Format("15:04:05"))

	// 确保在关闭channel前发送完最后的消息
	/*
		我已经修复了问题。主要的改动有两处：

		在 OnStart 中重新初始化消息队列，这确保每次服务启动时都会创建一个新的 channel，避免使用已关闭的 channel。同时也重置了消息 ID 计数器。

		改进了 OnStop 方法的关闭逻辑，添加了一个小的延迟，给生产者一个发送最后消息的机会，并增加了对 queue 和 messages channel 的空值检查，使停止过程更加安全。

		现在您可以试试多次启动停止服务，应该不会再出现 "send on closed channel" 的 panic 了。如果您还遇到其他问题，请告诉我。
	*/
	select {
	case <-ctx.Done():
	case <-time.After(time.Second):
	}

	if s.queue != nil && s.queue.messages != nil {
		close(s.queue.messages)
	}
	return nil
}
